package com.emailsystem.emailsystem.service.impl;
import com.emailsystem.emailsystem.dao.Impl.EmailDAO;
import com.emailsystem.emailsystem.dao.Impl.UserDAO;
import com.emailsystem.emailsystem.domain.Completion;
import com.emailsystem.emailsystem.domain.Email;
import com.emailsystem.emailsystem.util.Impl.FileUtilImpl;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.net.SocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.Socket;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

@Service
@Data
public class IMAPImpl {
    private Socket socket;
    private String account;

    @Autowired
    private EmailDAO emailDao;
    @Autowired
    private UserDAO userDao;


    public void init(String host, Integer port){
        try {
            if (993 == port) {
                SocketFactory socketFactory = SSLSocketFactory.getDefault();
                socket = socketFactory.createSocket(host, port);
                ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"});
            } else {
                socket = new Socket(host, port);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            System.out.println("成功建立连接！");
        }
    }

    //不改远程 因为不清楚现在这封邮件是第几封
//    public void update(BufferedReader br, PrintWriter pw) throws IOException {
//        sendServer2("store", "-", "35", "seen", br, pw);
//    }
    public static String getMessagedetail(BufferedReader br, String ending){
        StringBuilder message = new StringBuilder("");
        try {
            String line = br.readLine();

            while (null != line&&!line.equals(ending)&&!"a006 NO Folder not exist!".equals(line)) {
                message = message.append(line + "\r\n");
                line = br.readLine();
            }
            if(!"".equals(ending))message=message.append(line+"\r\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return message.toString();
    }

    /**
     *
     * @param action 执行的操作如：登录(login)、复制(copy)、标记(store)
     * @param str 此处为标记(store)需要的参数，str为"+"则为添加标记、为“-”则为去除标记
     * @param firstValue
     * @param secondValue
     * @param br
     * @param pw
     * @throws IOException
     */

    public static void sendServer2(String action, String str, String firstValue, String secondValue, BufferedReader br, PrintWriter pw) throws IOException {
        switch (action) {
            case "login":
                System.out.println("ready----------------："+br.readLine());
                int numberOfMillisecondsInTheFuture = 300; // 10 sec
                Date timeToRun = new Date(System.currentTimeMillis()+numberOfMillisecondsInTheFuture);
                Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    public void run() {
                        pw.println("a001 " + action + " " + firstValue + " " + secondValue);
                    }
                }, timeToRun);
                System.out.println("login----------------："+br.readLine());
                break;
            case "copy":
                // 第几封邮件 到邮箱
                pw.println("a002 " + action + " " + Integer.parseInt(firstValue) + " " + secondValue);
                System.out.println(br.toString());
                break;
            case "store":
                pw.println("a003 " + action + " " + firstValue + " " + str + "Flags (\\" + secondValue + ")");
                while ((str = br.readLine()) != null) {
                    if (str.equals("a003 OK STORE Completed"))
                        break;
                    System.out.println(str);
                }
                System.out.println("a003 OK STORE " + secondValue + " Completed");
                break;
            default:
                break;
        }

    }
    public static String sendServer(String action, String str, int num, String session, BufferedReader br, PrintWriter pw) throws IOException {
        String msg = "";
        switch (action) {
            case "noop" -> {
                pw.println("a004 noop");
                System.out.println(br.readLine());
            }
            case "list" -> {
                pw.println("a005 list \"\" *");
                System.out.println("a005 LIST");
                msg=getMessagedetail(br, "a005 OK LIST completed");
            }
            case "select" -> {
                pw.println("a006 select " + session);
                System.out.println("a006 SELECT " + session);
                msg= getMessagedetail(br, "a006 OK [READ-WRITE] SELECT complete");
            }
            case "fetch" -> {
                pw.println("a007 fetch " + num + " body[" + session + "]");
                msg=getMessagedetail(br,"a007 OK FETCH Completed");
                System.out.println("a007 OK FETCH " +num+" "+ session + " Completed");
                FileWriter fileWriter = new FileWriter("./imap.txt");
                fileWriter.append(msg);
                fileWriter.flush();
                fileWriter.close();
            }
            case "fetchFlag" -> {
                pw.println("a008 fetch " + num + " " + session);
                while ((str = br.readLine()) != null) {
                    if (str.equals("a008 OK FETCH Completed"))
                        break;
                    System.out.println(str);
                    if (str.contains("Flagged"))
                        System.out.println("Flagged");
                    if (str.contains("Seen"))
                        System.out.println("Seen");
                    if (str.contains("Deleted"))
                        System.out.println("Deleted");
                    if (str.contains("Draft"))
                        System.out.println("Draft");
                    if (str.contains("Answered"))
                        System.out.println("Answered");
                    return str;

                }
                System.out.println("a008 OK FETCH " + session + " Completed");
            }
            case "expunge" -> {//在不关闭邮箱的情况下删除所有标记为deleted的邮件，expunge命令删除的邮件不可恢复!
                pw.println("a008 expunge");
                msg=br.readLine();
            }
            case "logout" -> {//登出
                pw.println("a009 logout");
                System.out.println("a009 LOGOUT");
                msg=getMessagedetail(br,"* BYE LOGOUT received");
            }
            default -> {
            }
        }
        return msg;
    }


//    boxtype=> inbox sent drafts junk

////            System.out.println(sendServer("list", str, 0, "base", br, pw));
//    sendServer2("store", "+", "37", "draft", br, pw);
//    sendServer2("copy", str, "37", "drafts", br, pw);
//    sendServer2("store", "+", "30", "Answered", br, pw);
//    sendServer2("store", "-", "35", "seen", br, pw);

//
//    //            sendServer("store", "-", "116", "Flagged", br, pw);
////            sendServer("store", "+", "95", "Seen", br, pw);
//            sendServer("fetchFlag", str, 95, "flags", br, pw);
////            sendServer("copy", str, "117", "drafts", br, pw);

    public Integer getCurrentNums(String boxType,String account, String password) throws IOException{
        String str = "";
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        OutputStream outputStream = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(outputStream, true);
        sendServer2("login", str, account, password, br, pw);
        System.out.println(sendServer("noop", str, 0, "null", br, pw));

        String selectMsg=sendServer("select", str, 0, boxType, br, pw);
        System.out.println(selectMsg);

        //没有这个邮箱的话 数量-1
        if(selectMsg.contains("NO")){
            return -1;
        }

        int mailNumber=
                Integer.parseInt(selectMsg.substring(selectMsg.indexOf(" ")+1,selectMsg.indexOf("E")-1));
        return mailNumber;
    }
    //草稿箱要copy  差删除和收藏箱
    public void receiveEmail(String boxType,String account,String password,int begin,int length) throws IOException {
        try {
            String str = "";
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            OutputStream outputStream = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(outputStream, true);

            Completion completion = userDao.getCompletionByAccount(account);
            String WRONGID="$";

            for (int i = 0; i < length; i++) {
                StringBuilder sb=new StringBuilder("");
                sb.append(sendServer("fetch", str, begin, "header", br, pw));
                sb.append(sendServer("fetch", str, begin, "text", br, pw));
                String states=sendServer("fetchFlag", str, begin++, "flags", br, pw);
                String msg=sb.toString();
                try {
                    Email email = FileUtilImpl.DecodeIMAPMail(msg);
                    if (email != null) {
                        Integer existence = emailDao.selectExistenceByEmailID(email.getEmailID());
                        if (existence != null) {
//                        已存在,不要重复插入
                            continue;
                        }
                        if (states.contains("Flagged")) {
                            email.setFlagged(true);
                        }
                        if (states.contains("Seen")) {
                            email.setSeen(true);
                        }
                        if (states.contains("Deleted")) {
                            email.setDeleted(true);
                        }
                        //草稿无id 自己做id 用时间就行
                        if(boxType.equals("drafts"))email.setEmailID("draft_"+ email.getSendTime().replace(",","").trim());
                        emailDao.insertEmail(
                                email.getEmailID(), email.getSender(), email.getReceiver(), email.getSubject(), email.getContent(), email.getSendTime(),
                                email.getSenderNickname(), email.getReceiverNickname(), email.getSeen(), email.getFlagged(), email.getDeleted(), email.getAttachmentName());
                        // 然后记录行为
                        String Emails = switch (boxType) {
                            case "inbox" -> completion.getReceiveEmail();
                            case "drafts" -> completion.getDraftEmail();
                            case "favourite" -> completion.getFavouriteEmail();
                            case "sent" -> completion.getSentEmail();
                            case "rubbish" -> completion.getRubbishEmail();
                            default -> "";
                        };
                        if (Emails.length() > 0) Emails += "," + email.getEmailID();
                        else {
                            Emails = email.getEmailID();
                        }

                        //记录
                        switch (boxType) {
                            case "inbox" -> completion.setReceiveEmail(Emails);
                            case "drafts" -> completion.setDraftEmail(Emails);
                            case "favourite" -> completion.setFavouriteEmail(Emails);
                            case "sent" -> completion.setSentEmail(Emails);
                            case "rubbish" -> completion.setRubbishEmail(Emails);
                        }

                        //解析为空
                    }else{
                        String Emails = switch (boxType) {
                            case "inbox" -> completion.getReceiveEmail();
                            case "drafts" -> completion.getDraftEmail();
                            case "favourite" -> completion.getFavouriteEmail();
                            case "sent" -> completion.getSentEmail();
                            case "rubbish" -> completion.getRubbishEmail();
                            default -> "";
                        };
                        if (Emails.length() > 0) Emails += "," +WRONGID;
                        else {
                            Emails = WRONGID;
                        }
                        //记录
                        switch (boxType) {
                            case "inbox" -> completion.setReceiveEmail(Emails);
                            case "drafts" -> completion.setDraftEmail(Emails);
                            case "favourite" -> completion.setFavouriteEmail(Emails);
                            case "sent" -> completion.setSentEmail(Emails);
                            case "rubbish" -> completion.setRubbishEmail(Emails);
                        }
                    }


                    //解析失败

                }catch (Exception e) {
                    //解析异常 用 $ 凑个数 防止打乱我的逻辑
                    String Emails = switch (boxType) {
                        case "inbox" -> completion.getReceiveEmail();
                        case "drafts" -> completion.getDraftEmail();
                        case "favourite" -> completion.getFavouriteEmail();
                        case "sent" -> completion.getSentEmail();
                        case "rubbish" -> completion.getRubbishEmail();
                        default -> "";
                    };
                    if (Emails.length() > 0) Emails += "," +WRONGID;
                    else {
                        Emails = WRONGID;
                    }
                    //记录
                    switch (boxType) {
                        case "inbox" -> completion.setReceiveEmail(Emails);
                        case "drafts" -> completion.setDraftEmail(Emails);
                        case "favourite" -> completion.setFavouriteEmail(Emails);
                        case "sent" -> completion.setSentEmail(Emails);
                        case "rubbish" -> completion.setRubbishEmail(Emails);
                    }
                }
            }
            userDao.updateCompletion(completion.getSentEmail(),completion.getReceiveEmail(),completion.getFavouriteEmail(),completion.getDraftEmail(),completion.getRubbishEmail(),account);
            System.out.println(sendServer("logout", str, 0, "null", br, pw));
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            socket.close();
        }
    }
}